#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <syslog.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <stdbool.h>
#include <time.h>

pid_t child_pid = 0;

volatile sig_atomic_t is_shutdown = 0;

void signal_handler(int sig)
{
  switch (sig)
  {
  case SIGHUP:
    syslog(LOG_WARNING, "收到SIGHUP信号...");
    break;
  case SIGTERM:
    syslog(LOG_NOTICE, "接收到终止信号，准备退出守护进程...");
	if(child_pid > 0){
		syslog(LOG_NOTICE, "向子进程发送SIGTERM信号...");
		kill(child_pid, SIGTERM);
	}
	is_shutdown = 1;
    break;
  default:
    syslog(LOG_INFO, "Received unhandled signal");
  }
}

void my_daemonize(){
	pid_t pid;

	pid = fork();
	if(pid > 0){
		exit(0);
	}else if(pid < 0){
		exit(-1);
	}

	if(setsid() < 0){
		exit(-1);
	}
	// 处理 SIGHUP、SIGTERM 信号
  signal(SIGHUP, signal_handler);
  signal(SIGTERM, signal_handler);

  pid = fork();

  if (pid < 0)
    exit(EXIT_FAILURE);

  if (pid > 0)
    exit(EXIT_SUCCESS);

  // 重置umask
  umask(0);

  // 将工作目录切换为根目录
  chdir("/");

	// 关闭所有打开的文件描述符
  for (int x = 0; x <= sysconf(_SC_OPEN_MAX); x++)
  {
    close(x);
  }

  openlog("this is our daemonize process: ", LOG_PID, LOG_DAEMON);
}

int main(){
	time_t t;
	int fd;
	//创建守护进程
	my_daemonize();


	while(1){
		child_pid = fork();
		if(child_pid > 0){
			//守护进程
			syslog(LOG_INFO,"守护进程开始运行，持续更新时间信息");
			waitpid(-1,NULL,0);
			syslog(LOG_INFO,"waitpid: %d",(int)is_shutdown);
			if(is_shutdown == 1){
				syslog(LOG_INFO,"子进程已被回收，守护进程退出");
				closelog();
				exit(EXIT_SUCCESS);
			}
			syslog(LOG_ERR, "子进程意外退出，重启...");
      sleep(3);
		}else if(child_pid  == 0){
			signal(SIGTERM, SIG_DFL);
			signal(SIGHUP,SIG_IGN);

			fd = open("/home/orangepi/daemon.log", O_WRONLY | O_CREAT | O_APPEND,0644);
			if(fd == -1)
			{
				syslog(LOG_WARNING,"open error\n");
			}
			//被守护进程
			while(1){
			
				t = time(0);
				char *buf = asctime(localtime(&t));
				write(fd, buf, strlen(buf));
				sleep(10);
			}
			close(fd);
		}else
		{
			syslog(LOG_INFO,"failed to fork");
		}
	}

	return 0;
}
